import 'dart:math';
import 'dart:typed_data';

import '../BleManager.dart';
import '../bean/BleBeanInterface.dart';
import '../listener/OnBleConnectListener.dart';
import 'SendBean.dart';
import 'SendInterface.dart';
import 'SendProgressBean.dart';
import 'SendTask.dart';

///数据发送统一接口
class BleSendManager implements OnBleConnectListener {
  static BleSendManager? _instance;

  static BleSendManager get instance => _instance ??= BleSendManager._();

  ///数据发送接口
  final Map<String, SendInterface> _sendInterface = {};

  ///数据发送任务队列
  final List<SendTask> _sendTask = [];

  //当前正在处理的任务
  SendTask? _currentSendTask;

  //发送进度信息
  SendProgressBean sendProgressBean = SendProgressBean();

  BleSendManager._() {
    BleManager.instance.addConnectListener(this);
  }

  void send(List<SendBean> sendBeans, {SendCallback? onSuccess, SendProgress? onProgress, SendCallback? onError}) {
    SendTask sendTask = SendTask(sendBeans, onSuccess: onSuccess, onProgress: onProgress, onError: onError);
    _sendTask.add(sendTask);
    startSend();
  }

  void startSend() {
    if (_sendTask.isEmpty || _currentSendTask != null) {
      return;
    }
    sendProgressBean.progress = 0;
    _currentSendTask = _sendTask.removeAt(0);

    for (var sendBean in _currentSendTask!.sendBeans) {
      SendInterface? sendInterface = getSendInterface(sendBean.address);


      if (sendInterface == null) {
        sendBean.index = sendBean.getPackageCount();
        sendBean.onSuccess?.call("", Uint8List.fromList([]));
      } else {
        sendBean.onSuccess = onSuccess;
        sendBean.onProgress = onProgress;
        sendBean.onError = onError;
        sendInterface.send(sendBean);
      }
    }
  }

  void onFinish() {
    _currentSendTask = null;
    startSend();
  }

  SendInterface? getSendInterface(String address) {
    return _sendInterface[address];
  }

  int getTaskTotalCount() {
    int count = 0;
    if (_currentSendTask != null) {
      for (var sendBean in _currentSendTask!.sendBeans) {
        count += sendBean.getPackageCount();
      }
    }
    return count;
  }

  int getSuccessTaskCount() {
    int count = 0;
    if (_currentSendTask != null) {
      for (var sendBean in _currentSendTask!.sendBeans) {
        count += max(0, sendBean.index);
      }
    }
    return count;
  }

  void onSuccess(String msg, Uint8List data) {
    int totalTaskCount = getTaskTotalCount();
    int successTaskCount = getSuccessTaskCount();
    if (totalTaskCount <= successTaskCount) {
      //任务完成了
      _currentSendTask?.onSuccess?.call(msg, data);
      onFinish();
    } else {
      onProgress(0, 0);
    }
  }

  void onProgress(int totalTaskCount, int successTaskCount) {
    var taskTotalCount = getTaskTotalCount();
    var successTaskCount2 = getSuccessTaskCount();
    sendProgressBean.progress = successTaskCount2/taskTotalCount;
    _currentSendTask?.onProgress?.call(taskTotalCount, successTaskCount2);
  }

  void onError(String msg, Uint8List data) {
    int totalTaskCount = getTaskTotalCount();
    int successTaskCount = getSuccessTaskCount();
    if (totalTaskCount <= successTaskCount) {
      //任务完成了
      _currentSendTask?.onError?.call(msg, data);
      onFinish();
    } else {
      onProgress(0, 0);
    }
  }

  ///用mac地址获取蓝牙信息
  BleBeanInterface? getBleBean(String address) {
    return BleManager.instance.getBleBean(address);
  }

  @override
  void onConnected(String address) {
    var bean = getBleBean(address);
    if (bean == null) {
      return;
    }
    //配置发送数据接口
    if (!_sendInterface.containsKey(address)) {
      for (var checkBleSupport in BleManager.instance.checkBleSupport) {
        var b = checkBleSupport.isSupport(bean);
        if (b != null) {
          var impl = checkBleSupport.getSendInterface(b);
          if (impl == null) {
            continue;
          }
          _sendInterface[address] = impl;
          break;
        }
      }
    }
  }

  @override
  void onDisconnected(String address) {
    _sendInterface.remove(address);
  }

  @override
  void onMtuChanged(String address, int mtu) {}

  @override
  void onStartConnect(String address) {}
}
